//
//  PPNetworkManager.m
//  pickpic
//
//  Created by Jinxiao on 8/28/16.
//  Copyright © 2016 MicroDream. All rights reserved.
//

#import "PPNetworkManager.h"
#import "NSData+MD5Digest.h"
#import <AFNetworking/AFNetworking.h>

#import "PPLoginViewController.h"
#import "PPLoginNavigationController.h"

static NSString *const kBaseUrl = @"http://api.pickpic.cc/AppPickpic-v1/";//生产
//static NSString *const kBaseUrl = @"http://apitest.pickpic.cc:818/AppPickpic-v1/";
//static NSString *const kBaseUrl = @"http://api.int.cn/AppPickpic-v1/";//测试环境
static NSString *const kAppID = @"981ac9a8d8cbf97b1b532dbf7a8b7815";
static NSString *const kPrivateKey = @"f32f3a3cbcea8ade602843acb934f680";
static NSString *const kErrorDomain = @"com.pickpic.error";
static CGFloat const kRequestTimeoutInterval = 30.f;

@implementation PPNetworkManager

+ (instancetype)sharedInstance {
    static id instance;
    static dispatch_once_t once;
    dispatch_once(&once, ^{

        instance = [[self alloc] initWithBaseURL:[NSURL URLWithString:kBaseUrl] sessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    });

    return instance;
}

- (instancetype)initWithBaseURL:(NSURL *)url sessionConfiguration:(NSURLSessionConfiguration *)configuration {
    self = [super initWithBaseURL:url sessionConfiguration:configuration];

    if(self) {
        AFJSONRequestSerializer *requestSerializer = [AFJSONRequestSerializer serializer];
        [requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        self.requestSerializer = requestSerializer;
        [self.requestSerializer setTimeoutInterval:kRequestTimeoutInterval];

        self.responseSerializer = [AFJSONResponseSerializer serializer];
        self.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/JavaScript", @"text/html", @"text/plain", nil];
    }

    return self;
}

- (NSURLSessionTask *)post:(NSString *)url
                    params:(NSDictionary *)params
                  callback:(void (^)(id data, NSError *error))callback {

    NSString *token = DGCurrentAccount.credential.token;

    if(token.length > 0) {
        NSString *authorization = [NSString stringWithFormat:@"Bearer %@", token];
        [self.requestSerializer setValue:authorization forHTTPHeaderField:@"Authorization"];
    }

    NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    NSInteger rand = arc4random() % 10000000000000000; //生成0到16位的随机数

    NSDate *date = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    formatter.locale = [NSLocale systemLocale];
    formatter.dateFormat = @"yyyy-MM-dd-HH:mm:ss";
    NSString *dateString = [formatter stringFromDate:date];

    NSMutableString *commonString = [NSMutableString stringWithFormat:@"app_id=%@&plat=ios&private_key=%@&rand=%@&timestamp=%@&ver=%@", kAppID, kPrivateKey, @(rand), dateString, version];
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:nil];
    NSString *paramString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    [commonString appendFormat:@"&%@", paramString];

    NSData *signData = [commonString dataUsingEncoding:NSUTF8StringEncoding];
    NSString *sign = [signData MD5HexDigest];

    NSString *requestUrl = [NSString stringWithFormat:@"%@?app_id=%@&plat=%@&rand=%@&timestamp=%@&ver=%@&sign=%@", url, kAppID, @"ios", @(rand), dateString, version, sign];

    requestUrl = [requestUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    PPLog(@"请求接口 = %@ - %@",requestUrl,params);

    NSURLSessionDataTask *task = [self POST:requestUrl parameters:params progress:nil success:^(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) {
         PPLog(@"请求接口返回 = %@ - %@",requestUrl,responseObject);
        if(callback) {
            id data = [[responseObject validDictionary] valueForKey:@"result"];
            NSDictionary *err = [[responseObject validDictionary] validDictionaryForKey:@"err"];
            NSInteger code = [[err validNumberForKey:@"code"] integerValue];
            NSString *msg = [err validStringForKey:@"msg"];

            if(code == 0 && responseObject) {
                callback(data ? : @"OK", nil);
            } else {
                NSMutableDictionary *userInfo = [@{} mutableCopy];
                [userInfo setSafeObject:msg forKey:NSLocalizedDescriptionKey];
                NSError *error = [NSError errorWithDomain:kErrorDomain code:code userInfo:userInfo];
                callback(nil, error);
            }
        }
    } failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
        
        PPLog(@"url = %@ - %@",requestUrl,error);
        
        if(callback) {
            if(![self handleTokenExpirationWithTask:task error:error]) {
                NSMutableDictionary *userInfo = [@{} mutableCopy];
                [userInfo setSafeObject:@"网络异常，请检查网络连接" forKey:NSLocalizedDescriptionKey];
                NSError *newError = [NSError errorWithDomain:kErrorDomain code:8888 userInfo:userInfo];
                callback(nil, newError);
            }
        }
    }];

    return task;
}


- (NSURLSessionTask *)get:(NSString *)url
                   params:(NSDictionary *)params
                 callback:(void (^)(id data, NSError *error))callback {
    NSString *token = DGCurrentAccount.credential.token;

    if(token.length > 0) {
        NSString *authorization = [NSString stringWithFormat:@"Bearer %@", token];
        [self.requestSerializer setValue:authorization forHTTPHeaderField:@"Authorization"];
    }

    NSMutableDictionary *commonParams = [[NSMutableDictionary alloc] init];

    NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];

    [commonParams setSafeObject:version forKey:@"ver"];
    [commonParams setSafeObject:@"ios" forKey:@"plat"];
    [commonParams setSafeObject:kAppID forKey:@"app_id"];

    NSInteger rand = arc4random() % 10000000000000000; //生成0到16位的随机数
    [commonParams setSafeObject:@(rand) forKey:@"rand"];

    NSDate *date = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    formatter.locale = [NSLocale systemLocale];
    formatter.dateFormat = @"yyyy-MM-dd-HH:mm:ss";
    NSString *dateString = [formatter stringFromDate:date];

    [commonParams setSafeObject:dateString forKey:@"timestamp"];

    [commonParams setSafeObject:kPrivateKey forKey:@"private_key"];
    [commonParams addEntriesFromDictionary:params];

    //对commonParams里的参数进行排序
    NSArray *keys = [commonParams allKeys];
    NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult (id obj1, id obj2){
        return [obj1 compare:obj2 options:NSNumericSearch];
    }];

    NSMutableString *commonString = [[NSMutableString alloc] init];
    [sortedArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
        NSString *value = [commonParams validStringForKey:obj];

        if(value) {
            if(idx == 0) {

                [commonString appendFormat:@"%@=%@", obj, value];
            } else {
                [commonString appendFormat:@"&%@=%@", obj, value];
            }
        }
    }];

    NSData *signData = [commonString dataUsingEncoding:NSUTF8StringEncoding];
    NSString *sign = [signData MD5HexDigest];

    NSString *requestUrl = [NSString stringWithFormat:@"%@?app_id=%@&plat=%@&rand=%@&timestamp=%@&ver=%@&sign=%@", url, kAppID, @"ios", @(rand), dateString, version, sign];

    requestUrl = [requestUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    PPLog(@"请求地址 = %@",requestUrl);
    NSURLSessionDataTask *task = [self GET:requestUrl parameters:params progress:nil success:^(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) {
        PPLog(@"请求接口 = %@ - %@",requestUrl, [responseObject yy_modelToJSONString]);
        if(callback) {
            id data = [[responseObject validDictionary] valueForKey:@"result"];
            NSDictionary *err = [[responseObject validDictionary] validDictionaryForKey:@"err"];
            NSInteger code = [[err validNumberForKey:@"code"] integerValue];

            if(code == 0 && responseObject) {
                callback(data ? : @"OK", nil);
            } else {

                NSString *msg = [err validStringForKey:@"msg"];
                NSMutableDictionary *userInfo = [@{} mutableCopy];
                [userInfo setSafeObject:msg forKey:NSLocalizedDescriptionKey];
                NSError *error = [NSError errorWithDomain:kErrorDomain code:code userInfo:userInfo];
                callback(nil, error);
            }
        }
    } failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
        if(callback) {
            if(![self handleTokenExpirationWithTask:task error:error]) {
                NSMutableDictionary *userInfo = [@{} mutableCopy];
                [userInfo setSafeObject:@"网络异常，请检查网络连接" forKey:NSLocalizedDescriptionKey];
                NSError *newError = [NSError errorWithDomain:kErrorDomain code:8888 userInfo:userInfo];
                callback(nil, newError);
            }
        }
    }];

    return task;
}

- (BOOL)handleTokenExpirationWithTask:(NSURLSessionDataTask *)task error:(NSError *)error {
    //    NSInteger statusCode = [(NSHTTPURLResponse *)task.response statusCode];
    NSString *JSON = [[NSString alloc] initWithData:(NSData *)error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] encoding:NSUTF8StringEncoding];

    if(!JSON.length) {
        return NO;
    }

    NSData *data = [JSON dataUsingEncoding:NSUTF8StringEncoding];
    id parameters = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];

    NSInteger code = [parameters validNumberForKey:@"code"].integerValue;

    if(code == -100 || code == -101 || code == -102) {

        [[PPAccountManager sharedInstance] logoutWithCompletion:^(BOOL success) {
            if(success) {
                PPLoginViewController *loginViewController = [[UIStoryboard storyboardWithName:@"Login" bundle:nil] instantiateViewControllerWithIdentifier:@"PPLoginViewController"];
                PPLoginNavigationController *navigationController = [[PPLoginNavigationController alloc] initWithRootViewController:loginViewController];
                [[[UIApplication sharedApplication] delegate] window].rootViewController = navigationController;

                [loginViewController.navigationController.view toastMessage:@"请重新登录"];
            }
        }];
        

        return YES;
    }

    return NO;
}


///MARK:下载图片
+ (void)downLoadImageWithUrl:(NSString *)url callback:(void (^)(UIImage *downImage, NSError *error))callback {
    
        [[SDImageCache sharedImageCache] queryDiskCacheForKey:url done:^(UIImage *image, SDImageCacheType cacheType) {
            if (image) {
                callback(image,nil);
                PPLog(@"找到了 %@",url);
            }else{
            
                [[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:url] options:SDWebImageLowPriority progress:^(NSInteger receivedSize, NSInteger expectedSize) {
                    
                } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
                    
                    if (image) {
                        PPLog(@"下载到了 %@",url);
                        callback(image,nil);
                    }else{
                        NSMutableDictionary *userInfo = [@{} mutableCopy];
                        [userInfo setSafeObject:@"网络异常，请检查网络连接" forKey:NSLocalizedDescriptionKey];
                        NSError *newError = [NSError errorWithDomain:kErrorDomain code:8888 userInfo:userInfo];
                        callback(nil, newError);
                    }
                }];

            }
        }];
        
   }
- (void)checkNetworkStatusChangeBlock:(void (^)(PPNetStatus))netStatus
{
    //1.创建网络状态监测管理者
    //    [[AFNetworkReachabilityManager sharedManager] startMonitoring];
    AFNetworkReachabilityManager *manger = [AFNetworkReachabilityManager sharedManager];
    
    [manger startMonitoring];
    //2.监听改变
    [manger setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        /*
         AFNetworkReachabilityStatusUnknown          = -1,
         AFNetworkReachabilityStatusNotReachable     = 0,
         AFNetworkReachabilityStatusReachableViaWWAN = 1,
         AFNetworkReachabilityStatusReachableViaWiFi = 2,
         */
        
        
        
        switch (status) {
            case AFNetworkReachabilityStatusUnknown:{
                PPLog(@"未知");
                _networkStatus = PPNetStatusUnKnown;
                if (netStatus) {
                    netStatus(_networkStatus);
                }
            }
                break;
            case AFNetworkReachabilityStatusNotReachable:{
                PPLog(@"没有网络");
                _networkStatus = PPNetStatusNotReachable;
                if (netStatus) {
                    netStatus(_networkStatus);
                }
                
                [MBProgressHUD showError:@"请检查网络连接"];
            }
                break;
            case AFNetworkReachabilityStatusReachableViaWWAN:{
                PPLog(@"3G|4G");
                _networkStatus = PPNetStatusMobile;
                if (netStatus) {
                    netStatus(_networkStatus);
                }
            }
                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:{
                PPLog(@"WiFi");
                _networkStatus = PPNetStatusWIFI;
                if (netStatus) {
                    netStatus(_networkStatus);
                }
            }
                break;
            default:
                break;
        }
    }];
}


- (NSURLSessionTask *)postCreateEbook:(NSString *)url
                    params:(NSDictionary *)params
                    progress:(void (^)(NSProgress * _Nonnull))uploadProgress
                  callback:(void (^)(id data, NSError *error))callback {
    
    NSString *token = DGCurrentAccount.credential.token;
    
    if(token.length > 0) {
        NSString *authorization = [NSString stringWithFormat:@"Bearer %@", token];
        [self.requestSerializer setValue:authorization forHTTPHeaderField:@"Authorization"];
    }
    
    NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    NSInteger rand = arc4random() % 10000000000000000; //生成0到16位的随机数
    
    NSDate *date = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    formatter.locale = [NSLocale systemLocale];
    formatter.dateFormat = @"yyyy-MM-dd-HH:mm:ss";
    NSString *dateString = [formatter stringFromDate:date];
    
    NSMutableString *commonString = [NSMutableString stringWithFormat:@"app_id=%@&plat=ios&private_key=%@&rand=%@&timestamp=%@&ver=%@", kAppID, kPrivateKey, @(rand), dateString, version];
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:nil];
    NSString *paramString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    [commonString appendFormat:@"&%@", paramString];
    
    NSData *signData = [commonString dataUsingEncoding:NSUTF8StringEncoding];
    NSString *sign = [signData MD5HexDigest];
    
    NSString *requestUrl = [NSString stringWithFormat:@"%@?app_id=%@&plat=%@&rand=%@&timestamp=%@&ver=%@&sign=%@", url, kAppID, @"ios", @(rand), dateString, version, sign];
    
    requestUrl = [requestUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    PPLog(@"请求接口 = %@ - %@",requestUrl,params);
    
    NSURLSessionDataTask *task = [self POST:requestUrl parameters:params progress:uploadProgress success:^(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) {
        
        if(callback) {
            id data = [[responseObject validDictionary] valueForKey:@"result"];
            NSDictionary *err = [[responseObject validDictionary] validDictionaryForKey:@"err"];
            NSInteger code = [[err validNumberForKey:@"code"] integerValue];
            NSString *msg = [err validStringForKey:@"msg"];
            
            if(code == 0 && responseObject) {
                callback(data ? : @"OK", nil);
            } else {
                NSMutableDictionary *userInfo = [@{} mutableCopy];
                [userInfo setSafeObject:msg forKey:NSLocalizedDescriptionKey];
                NSError *error = [NSError errorWithDomain:kErrorDomain code:code userInfo:userInfo];
                callback(nil, error);
            }
        }
    } failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
        
        PPLog(@"url = %@ - %@",requestUrl,error);
        
        if(callback) {
            if(![self handleTokenExpirationWithTask:task error:error]) {
                NSMutableDictionary *userInfo = [@{} mutableCopy];
                [userInfo setSafeObject:@"网络异常，请检查网络连接" forKey:NSLocalizedDescriptionKey];
                NSError *newError = [NSError errorWithDomain:kErrorDomain code:8888 userInfo:userInfo];
                callback(nil, newError);
            }
        }
    }];
    
    return task;
}

- (void)DELETEData:(NSString *)url
                          params:(NSDictionary *)params
                        callback:(void (^)(id data, NSError *error))callback {
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.requestSerializer.timeoutInterval = kRequestTimeoutInterval;
    
    NSString *token = DGCurrentAccount.credential.token;
    
    if(token.length > 0) {
        NSString *authorization = [NSString stringWithFormat:@"Bearer %@", token];
        [manager.requestSerializer setValue:authorization forHTTPHeaderField:@"Authorization"];
    }

    NSMutableDictionary *commonParams = [[NSMutableDictionary alloc] init];
    
    NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    
    [commonParams setSafeObject:version forKey:@"ver"];
    [commonParams setSafeObject:@"ios" forKey:@"plat"];
    [commonParams setSafeObject:kAppID forKey:@"app_id"];
    
    NSInteger rand = arc4random() % 10000000000000000; //生成0到16位的随机数
    [commonParams setSafeObject:@(rand) forKey:@"rand"];
    
    NSDate *date = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    formatter.locale = [NSLocale systemLocale];
    formatter.dateFormat = @"yyyy-MM-dd-HH:mm:ss";
    NSString *dateString = [formatter stringFromDate:date];
    
    [commonParams setSafeObject:dateString forKey:@"timestamp"];
    
    [commonParams setSafeObject:kPrivateKey forKey:@"private_key"];
    [commonParams addEntriesFromDictionary:params];
    
    //对commonParams里的参数进行排序
    NSArray *keys = [commonParams allKeys];
    NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult (id obj1, id obj2){
        return [obj1 compare:obj2 options:NSNumericSearch];
    }];
    
    NSMutableString *commonString = [[NSMutableString alloc] init];
    [sortedArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
        NSString *value = [commonParams validStringForKey:obj];
        
        if(value) {
            if(idx == 0) {
                
                [commonString appendFormat:@"%@=%@", obj, value];
            } else {
                [commonString appendFormat:@"&%@=%@", obj, value];
            }
        }
    }];
    
    NSData *signData = [commonString dataUsingEncoding:NSUTF8StringEncoding];
    NSString *sign = [signData MD5HexDigest];
    
    NSString *requestUrl = [NSString stringWithFormat:@"%@%@?app_id=%@&plat=%@&rand=%@&timestamp=%@&ver=%@&sign=%@",kBaseUrl,url, kAppID, @"ios", @(rand), dateString, version, sign];
    
    requestUrl = [requestUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    PPLog(@"请求地址 = %@ - %@",requestUrl,params);
    [manager DELETE:requestUrl parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
         PPLog(@"请求地址SUCCESS = %@ - %@",responseObject,params);
        if(callback) {
            id data = [[responseObject validDictionary] valueForKey:@"result"];
            NSDictionary *err = [[responseObject validDictionary] validDictionaryForKey:@"err"];
            NSInteger code = [[err validNumberForKey:@"code"] integerValue];
            
            if(code == 0 && responseObject) {
                callback(data ? : @"OK", nil);
            } else {
                NSString *msg = [err validStringForKey:@"msg"];
                NSMutableDictionary *userInfo = [@{} mutableCopy];
                [userInfo setSafeObject:msg forKey:NSLocalizedDescriptionKey];
                NSError *error = [NSError errorWithDomain:kErrorDomain code:code userInfo:userInfo];
                callback(nil, error);
            }
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        if(callback) {
            PPLog(@"url = %@ - %@",requestUrl,error);
            if(![self handleTokenExpirationWithTask:task error:error]) {
                NSMutableDictionary *userInfo = [@{} mutableCopy];
                [userInfo setSafeObject:@"网络异常，请检查网络连接" forKey:NSLocalizedDescriptionKey];
                NSError *newError = [NSError errorWithDomain:kErrorDomain code:8888 userInfo:userInfo];
                callback(nil, newError);
            }
        }
    }];
    
}

@end

// ----------------- 华丽的分割线 （错误处理类）-------

@implementation PPError

@end
